#include "app_net.h"
#include "CH57x_common.h"
#include "stdint.h"
#include "CH57xBLE_LIB.H"
#include "eth_driver.h"
#include "MQTTPacket.h"
#include "mqtt.h"





uint8_t app_net_task_id;


#define KEEPLIVE_ENABLE                      1                                  /* 开启KEEPLIVE功能 */

/* 下面的缓冲区和全局变量必须要定义，库中调用 */
//__align(16)UINT8    CH57xMACRxDesBuf[(RX_QUEUE_ENTRIES )*16];                   /* MAC接收描述符缓冲区，16字节对齐 */
//__align(4) UINT8    CH57xMACRxBuf[RX_QUEUE_ENTRIES*RX_BUF_SIZE];                /* MAC接收缓冲区，4字节对齐 */
//__align(4) SOCK_INF SocketInf[CH57xNET_MAX_SOCKET_NUM];                         /* Socket信息表，4字节对齐 */

//UINT16 MemNum[8] = {CH57xNET_NUM_IPRAW,
//                    CH57xNET_NUM_UDP,
//                    CH57xNET_NUM_TCP,
//                    CH57xNET_NUM_TCP_LISTEN,
//                    CH57xNET_NUM_TCP_SEG,
//                    CH57xNET_NUM_IP_REASSDATA,
//                    CH57xNET_NUM_PBUF,
//                    CH57xNET_NUM_POOL_BUF
//                    };
// UINT16 MemSize[8] = {CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IPRAW_PCB),
//                    CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_UDP_PCB),
//                    CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB),
//                    CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB_LISTEN),
//                    CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_SEG),
//                    CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IP_REASSDATA),
//                    CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(0),
//                    CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_POOL_BUF)
//                    };
//__align(4)UINT8 Memp_Memory[CH57xNET_MEMP_SIZE];
//__align(4)UINT8 Mem_Heap_Memory[CH57xNET_RAM_HEAP_SIZE];
//__align(4)UINT8 Mem_ArpTable[CH57xNET_RAM_ARP_TABLE_SIZE];
/******************************************************************************/
/* 本演示程序的相关宏 */
//#define RECE_BUF_LEN                          536                               /* 接收缓冲区的大小 */
/* CH57xNET库TCP的MSS长度为536字节，即一个TCP包里的数据部分最长为536字节 */
/* TCP协议栈采用滑动窗口进行流控，窗口最大值为socket的接收缓冲区长度。在设定 */
/* RX_QUEUE_ENTRIES时要考虑MSS和窗口之间的关系，例如窗口值为4*MSS，则远端一次会发送 */
/* 4个TCP包，如果RX_QUEUE_ENTRIES小于4，则必然会导致数据包丢失，从而导致通讯效率降低 */
/* 建议RX_QUEUE_ENTRIES要大于( 窗口/MSS ),如果多个socket同时进行大批量发送数据，则 */ 
/* 建议RX_QUEUE_ENTRIES要大于(( 窗口/MSS )*socket个数) 在多个socket同时进行大批数据收发时 */
/* 为了节约RAM，请将接收缓冲区的长度设置为MSS */
																		
/* CH579相关定义 */
UINT8 MACAddr[6] = {0x84,0xc2,0xe4,0x02,0x03,0x04};                             /* CH579MAC地址 */
UINT8 IPAddr[4] = {192,168,10,200};                                                          /* CH579IP地址 */
UINT8 GWIPAddr[4] = {192,168,10,1};                                              /* CH579网关 */
UINT8 IPMask[4] = {255,255,255,0};                                              /* CH579子网掩码 */
UINT8 DESIP[4] = {192,168,10,7}; 
                                              /* 目的IP地址 */


uint16_t desport = 777;                               //destination port
uint16_t srcport = 1000;                               //source port

/* 网口灯定义 PB口低十六位有效 */
UINT16 CH57xNET_LEDCONN=0x0010;                                                 /* 连接指示灯 PB4 */
UINT16 CH57xNET_LEDDATA=0x0080;                                                 /* 通讯指示灯 PB7 */ 

UINT8 SocketId;                                                                 /* 保存socket索引，可以不用定义 */
UINT8 SocketRecvBuf[RECE_BUF_LEN];                                              /* socket接收缓冲区 */
UINT8 MyBuf[RECE_BUF_LEN];                                                      /* 定义一个临时缓冲区 */


UINT8 CH57xNET_DHCPCallBack(UINT8 status,void *arg);

uint8_t WCHNET_DHCPCallBack(uint8_t status, void *arg);
//extern const UINT16 *memp_num;

/*******************************************************************************
* Function Name  : IRQ_Handler
* Description    : IRQ中断服务函数
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void ETH_IRQHandler( void )						                             	/* 以太网中断 */
{
	//CH57xNET_ETHIsr();	
	    WCHNET_ETHIsr();							                              	

	/* 以太网中断中断服务函数 */
}

//void TMR0_IRQHandler( void ) 						                            /* 定时器中断 */
//{
//	CH57xNET_TimeIsr(CH57xNETTIMEPERIOD);                                       /* 定时器中断服务函数 */
//	R8_TMR0_INT_FLAG |= 0xff;						                            /* 清除定时器中断标志 */
//}



/*******************************************************************************
* Function Name  : mStopIfError
* Description    : 调试使用，显示错误代码
* Input          : iError 错误代码
* Output         : None
* Return         : None
*******************************************************************************/
void mStopIfError(UINT8 iError)
{
    if (iError == WCHNET_ERR_SUCCESS) return;                                 /* 操作成功 */
    PRINT("mStopIfError: %02X\r\n", (UINT16)iError);                            /* 显示错误 */
}
/*********************************************************************
 * @fn      WCHNET_CreateTcpSocket
 *
 * @brief   Create TCP Socket
 *
 * @return  none
 */
void WCHNET_CreateTcpSocket(void)
{
    uint8_t i;
    SOCK_INF TmpSocketInf;

    memset((void *) &TmpSocketInf, 0, sizeof(SOCK_INF));
    memcpy((void *) TmpSocketInf.IPAddr, DESIP, 4);
    TmpSocketInf.DesPort = desport;
    TmpSocketInf.SourPort = srcport;
    TmpSocketInf.ProtoType = PROTO_TYPE_TCP;
    TmpSocketInf.RecvBufLen = RECE_BUF_LEN;
    i = WCHNET_SocketCreat(&SocketId, &TmpSocketInf);
    printf("WCHNET_SocketCreat %d\r\n", SocketId);
    mStopIfError(i);
    i = WCHNET_SocketConnect(SocketId);                        //make a TCP connection
    mStopIfError(i);
}
/*********************************************************************
 * @fn      WCHNET_DataLoopback
 *
 * @brief   Data loopback function.
 *
 * @param   id - socket id.
 *
 * @return  none
 */
void WCHNET_DataLoopback(uint8_t id)
{
#if 0
    uint8_t i;
    uint32_t len;
    uint32_t endAddr = SocketInf[id].RecvStartPoint + SocketInf[id].RecvBufLen;       	//Receive buffer end address

    if ((SocketInf[id].RecvReadPoint + SocketInf[id].RecvRemLen) > endAddr) {    		//Calculate the length of the received data
        len = endAddr - SocketInf[id].RecvReadPoint;
    }
    else {
        len = SocketInf[id].RecvRemLen;
    }
    i = WCHNET_SocketSend(id, (uint8_t *) SocketInf[id].RecvReadPoint, &len);        	//send data
    if (i == WCHNET_ERR_SUCCESS) {
        WCHNET_SocketRecv(id, NULL, &len);                                      		//Clear sent data
    }
#else
    uint32_t len, totallen;
    uint8_t *p = MyBuf;

    len = WCHNET_SocketRecvLen(id, NULL);                                //query length
	  PRINT("Receive Len = %d\r\n",len);
    totallen = len;
    WCHNET_SocketRecv(id, MyBuf, &len);                                  //Read the data of the receive buffer into MyBuf
    while(1){
        len = totallen;
        WCHNET_SocketSend(id, p, &len);                                  //Send the data
        totallen -= len;                                                 //Subtract the sent length from the total length
        p += len;                                                        //offset buffer pointer
        if(totallen)continue;                                            //If the data is not sent, continue to send
        break;                                                           //After sending, exit
    }
#endif
}


/*******************************************************************************
* Function Name  : CH57xNET_CreatTcpSocket
* Description    : 创建TCP Client socket
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void CH57xNET_CreatTcpSocket(void)
{
//   UINT8 i;                                                             
//   SOCK_INF TmpSocketInf;                                                       /* 创建临时socket变量 */

//   memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF));                            /* 库内部会将此变量复制，所以最好将临时变量先全部清零 */
//   memcpy((void *)TmpSocketInf.IPAddr,DESIP,4);                                 /* 设置目的IP地址 */
//   TmpSocketInf.DesPort = 777;                     
//   TmpSocketInf.SourPort = 2000;                                                /* 设置源端口 */
//   TmpSocketInf.ProtoType = PROTO_TYPE_TCP;                                     /* 设置socekt类型 */
//   TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf;                         /* 设置接收缓冲区的接收缓冲区 */
//   TmpSocketInf.RecvBufLen = RECE_BUF_LEN ;                                     /* 设置接收缓冲区的接收长度 */
//   i = CH57xNET_SocketCreat(&SocketId,&TmpSocketInf);                           /* 创建socket，将返回的socket索引保存在SocketId中 */
//   mStopIfError(i);                                                             /* 检查错误 */
//#ifdef  KEEPLIVE_ENABLE
//   CH57xNET_SocketSetKeepLive( SocketId, 1 );                                   /* 开启socket的KEEPLIVE功能（V06版本支持） */
//#endif

//   i = CH57xNET_SocketConnect(SocketId);                                        /* TCP连接 */
//   mStopIfError(i);                                                             /* 检查错误 */
//   i = CH57xNET_SetSocketTTL( SocketId,128 );
//   mStopIfError(i);                                                             /* 检查错误 */
}


/*******************************************************************************
* Function Name  : net_initkeeplive
* Description    : keeplive初始化
* Input          : None      
* Output         : None
* Return         : None
*******************************************************************************/
#ifdef  KEEPLIVE_ENABLE
void net_initkeeplive(void)
{
//    struct _KEEP_CFG  klcfg;

//    klcfg.KLIdle = 20000;                                                       /* 空闲 */
//    klcfg.KLIntvl = 10000;                                                      /* 间隔 */
//    klcfg.KLCount = 5;                                                          /* 次数 */
//    CH57xNET_ConfigKeepLive(&klcfg);
}
#endif

/*******************************************************************************
* Function Name  : CH57xNET_LibInit
* Description    : 库初始化操作
* Input          : ip      ip地址指针
*                ：gwip    网关ip地址指针
*                : mask    掩码指针
*                : macaddr MAC地址指针 
* Output         : None
* Return         : 执行状态
*******************************************************************************/
//UINT8 CH57xNET_LibInit(/*const*/ UINT8 *ip,/*const*/ UINT8 *gwip,/*const*/ UINT8 *mask,/*const*/ UINT8 *macaddr)
//{
//    UINT8 i;
//    struct _CH57x_CFG cfg;

//    if(CH57xNET_GetVer() != CH57xNET_LIB_VER)return 0xfc;                       /* 获取库的版本号，检查是否和头文件一致 */
//    CH57xNETConfig = LIB_CFG_VALUE;                                             /* 将配置信息传递给库的配置变量 */
//    cfg.RxBufSize = RX_BUF_SIZE; 
//    cfg.TCPMss   = CH57xNET_TCP_MSS;
//    cfg.HeapSize = CH57x_MEM_HEAP_SIZE;
//    cfg.ARPTableNum = CH57xNET_NUM_ARP_TABLE;
//    cfg.MiscConfig0 = CH57xNET_MISC_CONFIG0;
//    CH57xNET_ConfigLIB(&cfg);
//    i = CH57xNET_Init(ip,gwip,mask,macaddr);
//#ifdef  KEEPLIVE_ENABLE
//    net_initkeeplive( );
//#endif
//    return (i);                      
//}

/*******************************************************************************
* Function Name  : CH57xNET_HandleSockInt
* Description    : Socket中断处理函数
* Input          : sockeid  socket索引
*                ：initstat 中断状态
* Output         : None
* Return         : None
*******************************************************************************/
void CH57xNET_HandleSockInt(UINT8 sockeid,UINT8 initstat)
{
    UINT32 len;
    UINT32 totallen;
    UINT8 *p = MyBuf;

    if(initstat & SINT_STAT_RECV)                                               /* 接收中断 */
    {
			
			#if 0
        len = CH57xNET_SocketRecvLen(sockeid,NULL);                             /* 查询长度 */
		PRINT("Receive Len = %d\r\n",len);                           
        totallen = len;
        CH57xNET_SocketRecv(sockeid,MyBuf,&len);                                /* 将接收缓冲区的数据读到MyBuf中*/
        while(1)
        {
           len = totallen;
           CH57xNET_SocketSend(sockeid,p,&len);                                 /* 将MyBuf中的数据发送 */
           totallen -= len;                                                     /* 将总长度减去以及发送完毕的长度 */
           p += len;                                                            /* 将缓冲区指针偏移*/
           if(totallen)continue;                                                /* 如果数据未发送完毕，则继续发送*/
           break;                                                               /* 发送完毕，退出 */
        }
				
				#endif
    }
    if(initstat & SINT_STAT_CONNECT)                                            /* TCP连接中断 */
    {   
			
			/* 产生此中断表示TCP已经连接，可以进行收发数据 */
        PRINT("TCP Connect Success\n");                           
    }
    if(initstat & SINT_STAT_DISCONNECT)                                         /* TCP断开中断 */
    {                                                                           /* 产生此中断，CH579库内部会将此socket清除，置为关闭*/
        PRINT("TCP Disconnect\n");                                              /* 应用曾需可以重新创建连接 */
    }
    if(initstat & SINT_STAT_TIM_OUT)                                            /* TCP超时中断 */
    {                                                                           /* 产生此中断，CH579库内部会将此socket清除，置为关闭*/
        PRINT("TCP Timout\n");                                                  /* 应用曾需可以重新创建连接 */

    }
}


///*******************************************************************************
//* Function Name  : CH57xNET_HandleGloableInt
//* Description    : 全局中断处理函数
//* Input          : None
//* Output         : None
//* Return         : None
//*******************************************************************************/
//void CH57xNET_HandleGlobalInt(void)
//{
//    UINT8 initstat;
//    UINT8 i;
//    UINT8 socketinit;
//    initstat = CH57xNET_GetGlobalInt();                                         /* 读全局中断状态并清除 */
//    if(initstat & GINT_STAT_UNREACH)                                            /* 不可达中断 */
//    {
//        PRINT("UnreachCode ：%d\n",CH57xInf.UnreachCode);                       /* 查看不可达代码 */
//        PRINT("UnreachProto ：%d\n",CH57xInf.UnreachProto);                     /* 查看不可达协议类型 */
//        PRINT("UnreachPort ：%d\n",CH57xInf.UnreachPort);                       /* 查询不可达端口 */       
//    }
//   if(initstat & GINT_STAT_IP_CONFLI)                                           /* IP冲突中断 */
//   {
//       PRINT("IP_CONFIL\r\n");
//   }
//   if(initstat & GINT_STAT_PHY_CHANGE)                                          /* PHY改变中断 */
//   {
//       i = CH57xNET_GetPHYStatus();                                             /* 获取PHY状态 */
//       PRINT("GINT_STAT_PHY_CHANGE %02x\n",i);
//			 if(i > 1) { //0-> disconnected 
//				 PRINT("start dhcp client \r\n");
//				 CH57xNET_DHCPStart(CH57xNET_DHCPCallBack); 
//			 }
//   }
//   if(initstat & GINT_STAT_SOCKET)                                              /* Socket中断 */
//   {
//		 PRINT("GINT_STAT_SOCKET\r\n");
//       for(i = 0; i < CH57xNET_MAX_SOCKET_NUM; i ++)                     
//       {
//           socketinit = CH57xNET_GetSocketInt(i);                               /* 读socket中断并清零 */
//           if(socketinit)CH57xNET_HandleSockInt(i,socketinit);                  /* 如果有中断则清零 */
//       }    
//   }
//}

/*********************************************************************
 * @fn      WCHNET_HandleSockInt
 *
 * @brief   Socket Interrupt Handle
 *
 * @param   socketid - socket id.
 *          intstat - interrupt status
 *
 * @return  none
 */
void WCHNET_HandleSockInt(uint8_t socketid, uint8_t intstat)
{
	
	uint32_t len;
    int qos, payloadlen;
    MQTTString topicName;
    unsigned short packetid;
    unsigned char retained, dup;
    unsigned char *payload;

    if(intstat & SINT_STAT_RECV)                                                //receive data
    {
        len = WCHNET_SocketRecvLen(socketid,NULL);
        WCHNET_SocketRecv(socketid,MyBuf,&len);
        switch(MyBuf[0]>>4)
        {
            case CONNACK:
                printf("CONNACK\r\n");
                //con_flag = 1;
                MQTT_Subscribe((char *)&mqtt_config.Subscribed_topic[0][0], 0);
								MQTT_Subscribe((char *)&mqtt_config.Subscribed_topic[1][0], 0);
								MQTT_Subscribe((char *)&mqtt_config.Subscribed_topic[2][0], 0);
								MQTT_Subscribe((char *)&mqtt_config.Subscribed_topic[3][0], 0);
						
								printf("Subscribed_topic %s\r\n",(char *)&mqtt_config.Subscribed_topic[0][0]);
								printf("Subscribed_topic %s\r\n",(char *)&mqtt_config.Subscribed_topic[1][0]);
								printf("Subscribed_topic %s\r\n",(char *)&mqtt_config.Subscribed_topic[2][0]);
								printf("Subscribed_topic %s\r\n",(char *)&mqtt_config.Subscribed_topic[3][0]);
                break;

            case PUBLISH:
                MQTTDeserialize_publish(&dup,&qos,&retained,&packetid,&topicName,
                                        &payload,&payloadlen,MyBuf,len);
                msgDeal(payload, payloadlen);
                break;

            case SUBACK:
                //sub_flag = 1;
                printf("SUBACK\r\n");
                break;

            default:
                break;
        }
        memset(MyBuf, 0 ,sizeof(MyBuf));
    }
	#if  0
    if (intstat & SINT_STAT_RECV)                               //receive data
    {
			#if 1
        WCHNET_DataLoopback(socketid);                          //Data loopback
			#endif
    }
	#endif
    if (intstat & SINT_STAT_CONNECT)                            //connect successfully
    {
      WCHNET_ModifyRecvBuf(socketid, (uint32_t) SocketRecvBuf, RECE_BUF_LEN);
      MQTT_Connect(mqtt_config.user_name, mqtt_config.passwd);  
			printf("TCP Connect Success\r\n");
    }
    if (intstat & SINT_STAT_DISCONNECT)                         //disconnect
    {
        printf("TCP Disconnect\r\n");
    }
    if (intstat & SINT_STAT_TIM_OUT)                            //timeout disconnect
    {
        printf("TCP Timeout\r\n");
				#if 1
        //WCHNET_CreateTcpSocket();
			       Transport_Open();

				#endif
    }
}
/*********************************************************************
 * @fn      WCHNET_HandleGlobalInt
 *
 * @brief   Global Interrupt Handle
 *
 * @return  none
 */
void WCHNET_HandleGlobalInt(void)
{
    uint8_t intstat;
    uint16_t i;
    uint8_t socketint;

    intstat = WCHNET_GetGlobalInt();                              //get global interrupt flag
    if (intstat & GINT_STAT_UNREACH)                              //Unreachable interrupt
    {
        printf("GINT_STAT_UNREACH\r\n");
    }
    if (intstat & GINT_STAT_IP_CONFLI)                            //IP conflict
    {
        printf("GINT_STAT_IP_CONFLI\r\n");
    }
    if (intstat & GINT_STAT_PHY_CHANGE)                           //PHY status change
    {
        i = WCHNET_GetPHYStatus();
        if (i & PHY_Linked_Status)
				{
				      printf("PHY Link Success i = %d\r\n",i);
				}else{
				      printf("PHY Link Disconnected\r\n");
				}
      
				
				if(i > 1) { //0-> disconnected 
				//				 PRINT("start dhcp client \r\n");
				//				 CH57xNET_DHCPStart(CH57xNET_DHCPCallBack); 
					
					 WCHNET_DHCPStart(WCHNET_DHCPCallBack);                       //Start DHCP
				}
    }
    if (intstat & GINT_STAT_SOCKET)                               //socket related interrupt
    {                             
        for (i = 0; i < WCHNET_MAX_SOCKET_NUM; i++) {
            socketint = WCHNET_GetSocketInt(i);
            if (socketint)
                WCHNET_HandleSockInt(i, socketint);
        }
    }
}


/*******************************************************************************
* Function Name  : Timer0Init
* Description    : 定时器1初始化
* Input          : time 定时时间
* Output         : None
* Return         : None
*******************************************************************************/
void Timer0Init(UINT32 time)
{
	R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR;	                                    /* 清除所有计数值 */
	R8_TMR0_CTRL_MOD = 0;					                                	/* 设置定时器模式 */
	R32_TMR0_CNT_END = FREQ_SYS/1000000*time;	                                /* 设置定时时间 */
	R8_TMR0_INT_FLAG = R8_TMR0_INT_FLAG;		                                /* 清除标志 */
	R8_TMR0_INTER_EN = RB_TMR_IE_CYC_END;	                                 	/* 定时中断 */
	R8_TMR0_CTRL_MOD |= RB_TMR_COUNT_EN;
	NVIC_EnableIRQ(TMR0_IRQn);	
}


/*******************************************************************************
* Function Name  : CH57xNET_DHCPCallBack
* Description    : DHCP回调函数
* Input          : None
* Output         : None
* Return         : 执行状态
*******************************************************************************/
UINT8 CH57xNET_DHCPCallBack(UINT8 status,void *arg)
{
   UINT8 *p;
   
   if(!status){                                                                  /* 成功*/
       p = arg;                                                                  /* 产生此中断，CH57xNET库内部会将此socket清除，置为关闭*/
       PRINT("DHCP Success\n");
       memcpy(IPAddr,p,4);
       memcpy(GWIPAddr,&p[4],4);
       memcpy(IPMask,&p[8],4);                                                   /* 产生此中断，CH57xNET库内部会将此socket清除，置为关闭*/
       PRINT("IPAddr = %d.%d.%d.%d \n",(UINT16)IPAddr[0],(UINT16)IPAddr[1],
              (UINT16)IPAddr[2],(UINT16)IPAddr[3]);
       PRINT("GWIPAddr = %d.%d.%d.%d \n",(UINT16)GWIPAddr[0],(UINT16)GWIPAddr[1],
              (UINT16)GWIPAddr[2],(UINT16)GWIPAddr[3]);
       PRINT("IPAddr = %d.%d.%d.%d \n",(UINT16)IPMask[0],(UINT16)IPMask[1],
              (UINT16)IPMask[2],(UINT16)IPMask[3]);
       PRINT("DNS1: %d.%d.%d.%d\n",p[12],p[13],p[14],p[15]);
       PRINT("DNS2: %d.%d.%d.%d\n",p[16],p[17],p[18],p[19]);
       tmos_set_event( app_net_task_id, APP_NET_TCP_RESTART );  // 创建tcp
   }
   else{ 
                                                                                 /* 产生此中断，CH57xNET库内部会将此socket清除，置为关闭*/
      PRINT("DHCP Fail %02x\n",status);
   }  
	 PRINT("dhcp stop \r\n");
		WCHNET_DHCPStop();	 
   return 0;
}


/*********************************************************************
 * @fn      WCHNET_DHCPCallBack
 *
 * @brief   DHCPCallBack
 *
 * @param   status - status returned by DHCP
 *          arg - Data returned by DHCP
 *
 * @return  DHCP status
 */
uint8_t WCHNET_DHCPCallBack(uint8_t status, void *arg)
{
    uint8_t *p;
    uint8_t tmp[4] = {0, 0, 0, 0};

    if(!status)
    {
        p = arg;
        printf("DHCP Success\r\n");
        /*If the obtained IP is the same as the last IP, exit this function.*/
        if(!memcmp(IPAddr, p ,sizeof(IPAddr)))
            return SUCCESS;
        /*Determine whether it is the first successful IP acquisition*/
        if(memcmp(IPAddr, tmp ,sizeof(IPAddr))){
            /*The obtained IP is different from the last value,
             * then disconnect the last connection.*/
            WCHNET_SocketClose(SocketId, TCP_CLOSE_NORMAL);
        }
        memcpy(IPAddr, p, 4);
        memcpy(GWIPAddr, &p[4], 4);
        memcpy(IPMask, &p[8], 4);
        printf("IPAddr = %d.%d.%d.%d \r\n", (uint16_t)IPAddr[0], (uint16_t)IPAddr[1],
               (uint16_t)IPAddr[2], (uint16_t)IPAddr[3]);
        printf("GWIPAddr = %d.%d.%d.%d \r\n", (uint16_t)GWIPAddr[0], (uint16_t)GWIPAddr[1],
               (uint16_t)GWIPAddr[2], (uint16_t)GWIPAddr[3]);
        printf("IPAddr = %d.%d.%d.%d \r\n", (uint16_t)IPMask[0], (uint16_t)IPMask[1],
               (uint16_t)IPMask[2], (uint16_t)IPMask[3]);
        printf("DNS1: %d.%d.%d.%d \r\n", p[12], p[13], p[14], p[15]);
        printf("DNS2: %d.%d.%d.%d \r\n", p[16], p[17], p[18], p[19]);
        //WCHNET_CreateTcpSocket();                                                   //Create a TCP connection
        tmos_set_event( app_net_task_id, APP_NET_TCP_RESTART );  // 创建tcp连接
				return SUCCESS;
    }
    else
    {
        printf("DHCP Fail %02x \r\n", status);
        /*Determine whether it is the first successful IP acquisition*/
        if(memcmp(IPAddr, tmp ,sizeof(IPAddr))){
            /*The obtained IP is different from the last value*/
            WCHNET_SocketClose(SocketId, TCP_CLOSE_NORMAL);
        }
        return FAILED;
    }
}




static void app_net_ProcessOSALMsg( tmos_event_hdr_t *pMsg ) {
    switch ( pMsg->event ) {
    case GATT_MSG_EVENT:
        break;

    default:
        break;
    }
}



uint16 app_net_process_event( uint8 task_id, uint16 events ) {

//  VOID task_id; // OSAL required parameter that isn't used in this function

    if ( events & SYS_EVENT_MSG ) {
        uint8 *pMsg;
        if ( (pMsg = tmos_msg_receive( app_net_task_id )) != NULL ) {
            app_net_ProcessOSALMsg( (tmos_event_hdr_t *)pMsg );
            // Release the OSAL message
            tmos_msg_deallocate( pMsg );
        }
        // return unprocessed events
        return (events ^ SYS_EVENT_MSG);
    }
    if ( events & APP_NET_START_EVT ) {
        PRINT("APP NET START_EVT\r\n");
        tmos_start_task( app_net_task_id, APP_NET_TIMES_10_MS,16 );  // 启动APP_NET_TIMES_10_MS事件
        tmos_start_task( app_net_task_id, APP_NET_TIMES_TICK,4 );  // 启动APP_NET_TIMES_TICK事件
        return ( events ^ APP_NET_START_EVT );
    }
    if( events & APP_NET_TIMES_10_MS) {
        //PRINT("12\r\n");
        // 此函数主要为 CH57xNET 库提供时钟，需要周期性的定时调用
        // 在TMOS应用中每10毫秒调用一下
			#if 0
        CH57xNET_TimeIsr(CH57xNETTIMEPERIOD); 
			#else			/* 给NET库提供时序 */
			WCHNET_TimeIsr(WCHNETTIMERPERIOD);
			#endif
        tmos_start_task( app_net_task_id, APP_NET_TIMES_10_MS,16 );  // 周期性执行APP_NET_TIMES_10_MS事件
        return ( events ^ APP_NET_TIMES_10_MS );
    }
    if(events & APP_NET_TIMES_TICK) {
        //CH57xNET_MainTask();
        WCHNET_MainTask();			
			/* CH57xNET库主任务函数，需要在主循环中不断调用 */
//        if(CH57xNET_QueryGlobalInt())CH57xNET_HandleGlobalInt();                /* 查询中断，如果有中断，则调用全局中断处理函数 */
		if(WCHNET_QueryGlobalInt())WCHNET_HandleGlobalInt();                /* 查询中断，如果有中断，则调用全局中断处理函数 */
			tmos_start_task( app_net_task_id, APP_NET_TIMES_TICK,4 );  // 周期性执行APP_NET_TIMES_TICK事件
        return ( events ^ APP_NET_TIMES_TICK );
    }
    if( events & APP_NET_TCP_RESTART) {

        PRINT("CH57xNET_CreatTcpSocket\r\n");
        PRINT("socket id %d\r\n",SocketId);
        //if(SocketId)
        //CH57xNET_CreatTcpSocket();
			  //WCHNET_CreateTcpSocket();  
			  Transport_Open();
        return (events ^ APP_NET_TCP_RESTART);
    }

    if(events & APP_NET_TIMES_TEST) {


        return (events ^ APP_NET_TIMES_TEST);
    }
    // Discard unknown events
    return 0;
}


/*******************************************************************************
* Function Name  : GetMacAddr
* Description    : 系统获取MAC地址
* Input          : pMAC:指向用来存储Mac地址的缓冲
* Output         : None
* Return         : None
*******************************************************************************/
void GetMacAddr(UINT8 *pMAC)
{
	UINT8 transbuf[6],i;
	
	GetMACAddress(transbuf);
	for(i=0;i<6;i++)
	{
		pMAC[5-i]=transbuf[i];
	
	}
}
void app_net_init(void) {
		uint8_t i;
    //when use ethernet must enable PLL at first 使用ETH必须开启PLL（PLL上电）
    PWR_UnitModCfg(ENABLE, UNIT_SYS_PLL);

       app_net_task_id = TMOS_ProcessEventRegister(app_net_process_event);  // 注册net任务
        
        #if 0
		GetMacAddr(MACAddr);                                                        /* 获取MAC地址 */
		i = CH57xNET_LibInit(IPAddr,GWIPAddr,IPMask,MACAddr);                       /* 库初始化 */
		mStopIfError(i);                                                            /* 检查错误 */
		PRINT("CH57xNETLibInit Success\r\n");  
        #else

            printf("net version:%x\n", WCHNET_GetVer());
            if ( WCHNET_LIB_VER != WCHNET_GetVer()) {
                printf("version error.\n");
            }
            WCHNET_GetMacAddr(MACAddr);                                  //get the chip MAC address
            printf("mac addr:");
            for ( i = 0; i < 6; i++)
                printf("%x ", MACAddr[i]);
            printf("\n");
            //Timer0Init(); 
            i = ETH_LibInit(IPAddr, GWIPAddr, IPMask, MACAddr);          //Ethernet library initialize
            mStopIfError(i);
            if (i == WCHNET_ERR_SUCCESS)
                printf("WCHNET_LibInit Success\r\n");
        #endif
						
						
						mqtt_init();
	
		NVIC_EnableIRQ(ETH_IRQn);	// 使能ETH中断
    tmos_set_event( app_net_task_id, APP_NET_START_EVT );  // 启动net
}

